package com.sd.aop;


import com.sd.entity.Log;
import com.sd.entity.User;
import com.sd.service.LogService;
import com.sd.util.MyUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Date;

/**
 * @author IvanZ
 * @version 1.0
 * @date Created on 2021/1/21 16:50
 * @description 日志切面类
 * @modifiedBy
 */
@EnableAspectJAutoProxy
@Aspect
@Component("logAspect")
public class LogAspect {
    @Autowired
    LogService logService;

    @Pointcut("execution(* com.sd.controller.*.*(..))")
    private void pt() {
    }

    @Around("pt()")
    public Object saveLog(ProceedingJoinPoint pjp) {
        Object rtValue = null;
        try {
            //得到方法所需的参数
            Object[] args = pjp.getArgs();

            //前置通知
            //类名
            String className = pjp.getTarget().getClass().getName();
            //方法名
            String methodName = pjp.getSignature().toString().split("\\.")[pjp.getSignature().toString().split("\\.").length - 1];

            /*for (Object arg : args) {
                Field[] declaredFields = arg.getClass().getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    setTime("createTime",declaredField,methodName,arg,"insert","add");
                    setTime("updateTime",declaredField,methodName,arg,"update","edit");
                }
            }*/

            //参数
            String params = Arrays.toString(pjp.getArgs());

            //获取ip
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            HttpServletRequest request = sra.getRequest();
            String ip = MyUtil.getRemoteAddr(request);
            //获取session中的user
            Log log = new Log();
            if (request.getSession().getAttribute("user") != null) {
                User user = (User) request.getSession().getAttribute("user");
                log.setLoginName(user.getLoginName());
                log.setUserName(user.getUserName());
            }

            log.setClassName(className);
            log.setMethodName(methodName);
            log.setParams(params);
            log.setIp(ip);
            //添加log
            logService.insert(log);

            //明确调用业务层方法（切入点方法）
            rtValue = pjp.proceed(args);

            return rtValue;
        } catch (Throwable throwable) {
            throw new RuntimeException(throwable);
        }
    }

    /**
     * 设置时间
     * @param fieldName:属性名
     * @param field:属性
     * @param methodName: 方法名
     * @param arg: 参数
     * @param contain1: 包含名字
     * @param contain2: 包含名字
     * @return void
     * @createBy IvanZ
     * @createTime 2021/1/22 16:34
     */
    public static void setTime(String fieldName,Field field,String methodName,Object arg,String contain1,String contain2) throws IllegalAccessException {
        if (fieldName.equals(field.getName())){
            //添加createTime和updateTime
            int start = methodName.indexOf("(") + 1;
            int end = methodName.indexOf(")");
            String[] paramTypes = methodName.substring(start, end).split(",");
            field.setAccessible(true);
            //实体类包名
            String packageName = "com.sd.entity";
            for (String paramType : paramTypes) {
                if (packageName.concat("." + paramType).equals(arg.getClass().getName())) {
                    if (methodName.contains(contain1) || methodName.contains(contain2)) {
                        field.set(arg, new Date());
                    }
                }
            }
        }
    }
}
